home *** CD-ROM | disk | FTP | other *** search
/ PC World 2008 September / PCWorld_2008-09_cd.bin / v cisle / sadanastroju / greasemonkey-0.8.20080609.0-fx.xpi / chrome / greasemonkey.jar / chromeFiles / content / scriptdownloader.js < prev    next >
Text File  |  2008-06-09  |  9KB  |  282 lines

  1. function ScriptDownloader(win, uri, bundle) {
  2.   this.win_ = win;
  3.   this.uri_ = uri;
  4.   this.bundle_ = bundle;
  5.   this.req_ = null;
  6.   this.script = null;
  7.   this.depQueue_ = [];
  8.   this.dependenciesLoaded_ = false;
  9.   this.installOnCompletion_ = false;
  10.   this.tempFiles_ = [];
  11. }
  12.  
  13. ScriptDownloader.prototype.startInstall = function() {
  14.   this.installing_ = true;
  15.   this.startDownload();
  16. };
  17.  
  18. ScriptDownloader.prototype.startViewScript = function(uri) {
  19.   this.installing_ = false;
  20.   this.startDownload();
  21. };
  22.  
  23. ScriptDownloader.prototype.startDownload = function() {
  24.   this.win_.GM_BrowserUI.statusImage.src = "chrome://global/skin/throbber/Throbber-small.gif";
  25.   this.win_.GM_BrowserUI.statusImage.style.opacity = "0.5";
  26.   this.win_.GM_BrowserUI.statusImage.tooltipText = this.bundle_.getString("tooltip.loading");
  27.  
  28.   this.win_.GM_BrowserUI.showStatus("Fetching user script", false);
  29.  
  30.   Components.classes["@greasemonkey.mozdev.org/greasemonkey-service;1"]
  31.     .getService().wrappedJSObject
  32.     .ignoreNextScript();
  33.  
  34.   this.req_ = new XMLHttpRequest();
  35.   this.req_.open("GET", this.uri_.spec, true);
  36.   this.req_.onload = GM_hitch(this, "handleScriptDownloadComplete");
  37.   this.req_.send(null);
  38. };
  39.  
  40. ScriptDownloader.prototype.handleScriptDownloadComplete = function() {
  41.   this.win_.GM_BrowserUI.refreshStatus();
  42.   this.win_.GM_BrowserUI.hideStatusImmediately();
  43.  
  44.   try {
  45.     // If loading from file, status might be zero on success
  46.     if (this.req_.status != 200 && this.req_.status != 0) {
  47.       // NOTE: Unlocalized string
  48.       alert("Error loading user script:\n" +
  49.       this.req_.status + ": " +
  50.       this.req_.statusText);
  51.       return;
  52.     }
  53.  
  54.     var source = this.req_.responseText;
  55.  
  56.     this.script = GM_getConfig().parse(source, this.uri_);
  57.  
  58.     var file = Components.classes["@mozilla.org/file/directory_service;1"]
  59.                          .getService(Components.interfaces.nsIProperties)
  60.                          .get("TmpD", Components.interfaces.nsILocalFile);
  61.  
  62.     var base = this.script.name.replace(/[^A-Z0-9_]/gi, "").toLowerCase();
  63.     file.append(base + ".user.js");
  64.     file.createUnique(
  65.       Components.interfaces.nsILocalFile.NORMAL_FILE_TYPE,
  66.       0640
  67.     );
  68.     this.tempFiles_.push(file);
  69.  
  70.     var converter =
  71.       Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
  72.         .createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
  73.     converter.charset = "UTF-8";
  74.     source = converter.ConvertFromUnicode(source);
  75.  
  76.     var ws = getWriteStream(file);
  77.     ws.write(source, source.length);
  78.     ws.close();
  79.  
  80.     this.script.setDownloadedFile(file);
  81.  
  82.     window.setTimeout(GM_hitch(this, "fetchDependencies"), 0);
  83.  
  84.     if(this.installing_){
  85.       this.showInstallDialog();
  86.     }else{
  87.       this.showScriptView();
  88.     }
  89.   } catch (e) {
  90.     // NOTE: unlocalized string
  91.     alert("Script could not be installed " + e);
  92.     throw e;
  93.   }
  94. };
  95.  
  96. ScriptDownloader.prototype.fetchDependencies = function(){
  97.   GM_log("Fetching Dependencies");
  98.   var deps = this.script.requires.concat(this.script.resources);
  99.   for (var i = 0; i < deps.length; i++) {
  100.     var dep = deps[i];
  101.     if (this.checkDependencyURL(dep.urlToDownload)) {
  102.       this.depQueue_.push(dep);
  103.     } else {
  104.       this.errorInstallDependency(this.script, dep,
  105.         "SecurityException: Request to local and chrome url's is forbidden");
  106.       return;
  107.     }
  108.   }
  109.   this.downloadNextDependency();
  110. };
  111.  
  112. ScriptDownloader.prototype.downloadNextDependency = function(){
  113.   if (this.depQueue_.length > 0) {
  114.     var dep = this.depQueue_.pop();
  115.     try {
  116.       var persist = Components.classes[
  117.         "@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
  118.         .createInstance(Components.interfaces.nsIWebBrowserPersist);
  119.       persist.persistFlags =
  120.         persist.PERSIST_FLAGS_BYPASS_CACHE |
  121.         persist.PERSIST_FLAGS_REPLACE_EXISTING_FILES; //doesn't work?
  122.       var ioservice =
  123.         Components.classes["@mozilla.org/network/io-service;1"]
  124.         .getService(Components.interfaces.nsIIOService);
  125.       var sourceUri = ioservice.newURI(dep.urlToDownload, null, null);
  126.       var sourceChannel = ioservice.newChannelFromURI(sourceUri);
  127.       sourceChannel.notificationCallbacks = new NotificationCallbacks();
  128.  
  129.       var file = getTempFile();
  130.       this.tempFiles_.push(file);
  131.  
  132.       var progressListener = new PersistProgressListener(persist);
  133.       progressListener.onFinish = GM_hitch(this,
  134.         "handleDependencyDownloadComplete", dep, file, sourceChannel);
  135.       persist.progressListener = progressListener;
  136.  
  137.       persist.saveChannel(sourceChannel,  file);
  138.     } catch(e) {
  139.       GM_log("Download exception " + e);
  140.       this.errorInstallDependency(this.script, dep, e);
  141.     }
  142.   } else {
  143.     this.dependenciesLoaded_ = true;
  144.     this.finishInstall();
  145.   }
  146. };
  147.  
  148. ScriptDownloader.prototype.handleDependencyDownloadComplete =
  149. function(dep, file, channel) {
  150.   GM_log("Dependency Download complete " + dep.urlToDownload);
  151.   try {
  152.     var httpChannel =
  153.       channel.QueryInterface(Components.interfaces.nsIHttpChannel);
  154.   } catch(e) {
  155.     var httpChannel = false;
  156.   }
  157.  
  158.   if (httpChannel) {
  159.     if (httpChannel.requestSucceeded) {
  160.       dep.setDownloadedFile(file, channel.contentType, channel.contentCharset ? channel.contentCharset : null);
  161.       this.downloadNextDependency();
  162.     } else {
  163.       this.errorInstallDependency(this.script, dep,
  164.         "Error! Server Returned : " + httpChannel.responseStatus + ": " +
  165.         httpChannel.responseStatusText);
  166.     }
  167.   } else {
  168.     dep.setDownloadedFile(file);
  169.     this.downloadNextDependency();
  170.   }
  171. };
  172.  
  173. ScriptDownloader.prototype.checkDependencyURL = function(url) {
  174.   var ioService = Components.classes["@mozilla.org/network/io-service;1"]
  175.                             .getService(Components.interfaces.nsIIOService);
  176.   var scheme = ioService.extractScheme(url);
  177.  
  178.   switch (scheme) {
  179.     case "http":
  180.     case "https":
  181.     case "ftp":
  182.         return true;
  183.     case "file":
  184.         var scriptScheme = ioService.extractScheme(this.uri_.spec);
  185.         return (scriptScheme == "file")
  186.     default:
  187.       return false;
  188.   }
  189. };
  190.  
  191. ScriptDownloader.prototype.finishInstall = function(){
  192.   if (this.installOnCompletion_) {
  193.     this.installScript();
  194.   }
  195. };
  196.  
  197. ScriptDownloader.prototype.errorInstallDependency = function(script, dep, msg){
  198.   GM_log("Error loading dependency " + dep.urlToDownload + "\n" + msg)
  199.   if (this.installOnCompletion_) {
  200.     alert("Error loading dependency " + dep.urlToDownload + "\n" + msg);
  201.   } else {
  202.     this.dependencyError = "Error loading dependency " + dep.urlToDownload + "\n" + msg;
  203.   }
  204. };
  205.  
  206. ScriptDownloader.prototype.installScript = function(){
  207.   if (this.dependencyError) {
  208.     alert(this.dependencyError);
  209.   } else if(this.dependenciesLoaded_) {
  210.     this.win_.GM_BrowserUI.installScript(this.script)
  211.   } else {
  212.     this.installOnCompletion_ = true;
  213.   }
  214. };
  215.  
  216. ScriptDownloader.prototype.cleanupTempFiles = function() {
  217.   for (var i = 0, file = null; file = this.tempFiles_[i]; i++) {
  218.     file.remove(false);
  219.   }
  220. };
  221.  
  222. ScriptDownloader.prototype.showInstallDialog = function(timer) {
  223.   if (!timer) {
  224.     // otherwise, the status bar stays in the loading state.
  225.     this.win_.setTimeout(GM_hitch(this, "showInstallDialog", true), 0);
  226.     return;
  227.   }
  228.   this.win_.openDialog("chrome://greasemonkey/content/install.xul", "",
  229.                        "chrome,centerscreen,modal,dialog,titlebar,resizable",
  230.                        this);
  231. };
  232.  
  233. ScriptDownloader.prototype.showScriptView = function() {
  234.   this.win_.GM_BrowserUI.showScriptView(this);
  235. };
  236.  
  237. function NotificationCallbacks() {}
  238.  
  239. NotificationCallbacks.prototype.QueryInterface = function(aIID) {
  240.   if (aIID.equals(Components.interfaces.nsIInterfaceRequestor)) {
  241.     return this;
  242.   }
  243.   throw Components.results.NS_NOINTERFACE;
  244. };
  245.  
  246. NotificationCallbacks.prototype.getInterface = function(aIID) {
  247.   if (aIID.equals(Components.interfaces.nsIAuthPrompt )) {
  248.      var winWat = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
  249.                             .getService(Components.interfaces.nsIWindowWatcher);
  250.      return winWat.getNewAuthPrompter(winWat.activeWindow);
  251.   }
  252.   return undefined;
  253. };
  254.  
  255.  
  256. function PersistProgressListener(persist) {
  257.   this.persist = persist;
  258.   this.onFinish = function(){};
  259.   this.persiststate = "";
  260. }
  261.  
  262. PersistProgressListener.prototype.QueryInterface = function(aIID) {
  263.  if (aIID.equals(Components.interfaces.nsIWebProgressListener)) {
  264.    return this;
  265.  }
  266.  throw Components.results.NS_NOINTERFACE;
  267. };
  268.  
  269. // nsIWebProgressListener
  270. PersistProgressListener.prototype.onProgressChange =
  271.   PersistProgressListener.prototype.onLocationChange =
  272.     PersistProgressListener.prototype.onStatusChange =
  273.       PersistProgressListener.prototype.onSecurityChange = function(){};
  274.  
  275. PersistProgressListener.prototype.onStateChange =
  276.   function(aWebProgress, aRequest, aStateFlags, aStatus) {
  277.     if (this.persist.currentState == this.persist.PERSIST_STATE_FINISHED) {
  278.       GM_log("Persister: Download complete " + aRequest.status);
  279.       this.onFinish();
  280.     }
  281.   };
  282.